home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / c_lang / strpp31.zip / STR.CPP < prev    next >
C/C++ Source or Header  |  1994-04-18  |  21KB  |  988 lines

  1. /* -------------------------------------------------------------------- */
  2. /* String++ Version 3.10                                       04/13/94 */
  3. /*                                                                      */
  4. /* Enhanced string class for Turbo C++/Borland C++.                     */
  5. /* Copyright 1991-1994 by Carl W. Moreland                              */
  6. /*                                                                      */
  7. /* str.cpp                                                              */
  8. /* -------------------------------------------------------------------- */
  9.  
  10. #ifndef __STDIO_H
  11. #include <stdio.h>
  12. #endif
  13. #ifndef __STDLIB_H
  14. #include <stdlib.h>
  15. #endif
  16.  
  17. #include "str.h"
  18.  
  19. const StrPP STR_NULL = "";
  20.  
  21. int    StrPP::strMinLength = 16;
  22. int    StrPP::strIncLength = 8;
  23. int  (*StrPP::strCompare)(const char*, const char*) = strcmp;
  24. int  (*StrPP::strToUpper)(int c) = ::toupper;
  25. int  (*StrPP::strToLower)(int c) = ::tolower;
  26. StrPP* StrPP::findIn  = 0;
  27. StrPP& StrPP::findStr = (StrPP&)STR_NULL;
  28. int    StrPP::findPos = 0;
  29. StrPP  StrPP::fpFormat("%0.4f");
  30.  
  31. /* ----- Constructors/Destructors ------------------------------------- */
  32.  
  33. StrPP::StrPP()
  34. {
  35.   Init();
  36. }
  37.  
  38. StrPP::StrPP(const char c, const int n)
  39. {
  40.   Init();
  41.   SetStr(c, n);
  42. }
  43.  
  44. StrPP::StrPP(const char* p)
  45. {
  46.   Init();
  47.   SetStr(p);
  48. }
  49.  
  50. StrPP::StrPP(const char* p, const int pos, const int len)
  51. {
  52.   Init();
  53.   SetStr(p, pos, len);
  54. }
  55.  
  56. StrPP::StrPP(const StrPP& s)
  57. {
  58.   Init();
  59.   SetStr(s);
  60. }
  61.  
  62. StrPP::StrPP(const StrPP& s, const int pos, const int len)
  63. {
  64.   Init();
  65.   SetStr(s, pos, len);
  66. }
  67.  
  68. StrPP::StrPP(const int n)
  69. {
  70.   Init();
  71.   ltos((long)n);
  72. }
  73.  
  74. StrPP::StrPP(const unsigned int n)
  75. {
  76.   Init();
  77.   ultos((unsigned long)n);
  78. }
  79.  
  80. StrPP::StrPP(const long n)
  81. {
  82.   Init();
  83.   ltos(n);
  84. }
  85.  
  86. StrPP::StrPP(const unsigned long n)
  87. {
  88.   Init();
  89.   ultos(n);
  90. }
  91.  
  92. StrPP::StrPP(const float n, const char* format)
  93. {
  94.   Init();
  95.   dtos((double)n, format);
  96. }
  97.  
  98. StrPP::StrPP(const double n, const char* format)
  99. {
  100.   Init();
  101.   dtos(n, format);
  102. }
  103.  
  104. StrPP::~StrPP(void)
  105. {
  106.   if(strPtr)
  107.     delete strPtr;
  108. }
  109.  
  110. /* ----- SetStr/AddStr ------------------------------------------------ */
  111.  
  112. void StrPP::SetStr(const char c, const int n)
  113. {
  114.   int i;
  115.   strLen = n;
  116.  
  117.   if(bufferLen > strLen)        // if the buffer is large enough...
  118.   {
  119.     for(i=0; i<strLen; i++)
  120.       strPtr[i] = c;            // copy n chars
  121.   }
  122.   else                    // else create a new buffer
  123.   {
  124.     if(strPtr)
  125.       delete strPtr;
  126.  
  127.     strPtr = new char[GetSize(strLen)];    // allocate the memory
  128.  
  129.     for(i=0; i<strLen; i++)
  130.       strPtr[i] = c;             // copy n chars
  131.   }
  132.   strPtr[strLen] = 0;            // add NULL termination
  133. }
  134.  
  135. void StrPP::SetStr(const char* p)
  136. {
  137.   strLen = strlen(p);
  138.  
  139.   if(bufferLen > strLen)        // if the buffer is large enough...
  140.     memcpy(strPtr, p, strLen);        // copy the string
  141.   else                    // else create a new buffer
  142.   {
  143.     char* tmp = new char[GetSize(strLen)];
  144.     memcpy(tmp, p, strLen);        // copy the string
  145.  
  146.     if(strPtr)
  147.       delete strPtr;
  148.     strPtr = tmp;            // now make strPtr = tmp
  149.   }
  150.   strPtr[strLen] = 0;            // add NULL termination
  151. }
  152.  
  153. void StrPP::SetStr(const char* p, const int pos, const int len)
  154. {
  155.   int p_len = strlen(p);
  156.  
  157.   if(pos > p_len)            // error check the start pos
  158.     return;
  159.  
  160.   strLen = p_len - pos;
  161.   if(len < strLen)            // error check the copy length
  162.     strLen = len;
  163.  
  164.   if(bufferLen > strLen)        // if the buffer is large enough...
  165.     memcpy(strPtr, p+pos, strLen);    // copy the substring
  166.   else                    // else create a new buffer
  167.   {
  168.     char* tmp = new char[GetSize(strLen)];
  169.     memcpy(tmp, p+pos, strLen);        // copy the substring
  170.  
  171.     if(strPtr)
  172.       delete strPtr;
  173.     strPtr = tmp;            // now make strPtr = tmp
  174.   }
  175.   strPtr[strLen] = 0;            // add NULL termination
  176. }
  177.  
  178. void StrPP::SetStr(const StrPP& s)
  179. {
  180.   strLen = s.strLen;
  181.  
  182.   if(bufferLen > strLen)        // if the buffer is large enough...
  183.     memcpy(strPtr, s.strPtr, strLen);    // copy the string
  184.   else                    // else create a new buffer
  185.   {
  186.     char* tmp = new char[GetSize(strLen)];
  187.     memcpy(tmp, s.strPtr, strLen);    // copy the string
  188.  
  189.     if(strPtr)
  190.       delete strPtr;
  191.     strPtr = tmp;            // now make strPtr = tmp
  192.   }
  193.   strPtr[strLen] = 0;            // add NULL termination
  194. }
  195.  
  196. void StrPP::SetStr(const StrPP& s, const int pos, const int len)
  197. {
  198.   if(pos > s.strLen)            // error check the start pos
  199.     return;
  200.  
  201.   strLen = s.strLen - pos;
  202.   if(len < strLen)            // error check the copy length
  203.     strLen = len;
  204.  
  205.   if(bufferLen > strLen)           // if the buffer is large enough...
  206.     memcpy(strPtr, s.strPtr+pos, strLen);  // copy the substring
  207.   else                       // else create a new buffer
  208.   {
  209.     char* tmp = new char[GetSize(strLen)]; // allocate new memory
  210.     memcpy(tmp, s.strPtr+pos, strLen);       // copy the substring
  211.  
  212.     if(strPtr)
  213.       delete strPtr;
  214.     strPtr = tmp;            // now make strPtr = tmp
  215.   }
  216.   strPtr[strLen] = 0;            // add NULL termination
  217. }
  218.  
  219. void StrPP::AddStr(const char c)
  220. {
  221.   strLen += 1;
  222.  
  223.   if(bufferLen > strLen)        // if the buffer is large enough...
  224.     strPtr[strLen-1] = c;        // append character c
  225.   else                    // else create a new buffer
  226.   {
  227.     char* tmp = new char[GetSize(strLen)];
  228.     memcpy(tmp, strPtr, strLen-1);    // copy the original string
  229.     tmp[strLen-1] = c;            // append character c
  230.  
  231.     if(strPtr)
  232.       delete strPtr;
  233.     strPtr = tmp;            // now make strPtr = tmp
  234.   }
  235.   strPtr[strLen] = 0;            // add NULL termination
  236. }
  237.  
  238. void StrPP::AddStr(const char* p)
  239. {
  240.   int s_len = strlen(p);
  241.  
  242.   if(bufferLen > strLen+s_len)        // if the buffer is large enough...
  243.     memcpy(strPtr+strLen, p, s_len);    // append StrPP p
  244.   else                    // else create a new buffer
  245.   {
  246.     char* tmp = new char[GetSize(strLen+s_len)];
  247.     memcpy(tmp, strPtr, strLen);    // copy the original string
  248.     memcpy(tmp+strLen, p, s_len);    // append string p
  249.  
  250.     if(strPtr)
  251.       delete strPtr;
  252.     strPtr = tmp;            // now make strPtr = tmp
  253.   }
  254.   strLen += s_len;
  255.   strPtr[strLen] = 0;            // add NULL termination
  256. }
  257.  
  258. void StrPP::AddStr(const StrPP& s)
  259. {
  260.   if(bufferLen > strLen + s.strLen)    // if the buffer is large enough...
  261.     memcpy(strPtr+strLen, s.strPtr, s.strLen);    // append string s
  262.   else                    // else create a new buffer
  263.   {
  264.     char* tmp = new char[GetSize(strLen+s.strLen)];
  265.     memcpy(tmp, strPtr, strLen);    // copy the original StrPP
  266.     memcpy(tmp+strLen, s.strPtr, s.strLen);    // append StrPP s
  267.  
  268.     if(strPtr)
  269.       delete strPtr;
  270.     strPtr = tmp;            // now make strPtr = tmp
  271.   }
  272.   strLen += s.strLen;
  273.   strPtr[strLen] = 0;            // add NULL termination
  274. }
  275.  
  276. // long to string
  277. void StrPP::ltos(const long n)
  278. {
  279.   char num[15];
  280.   ltoa(n, num, 10);
  281.  
  282.   SetStr(num);
  283. }
  284.  
  285. // unsigned long to string
  286. void StrPP::ultos(const unsigned long n)
  287. {
  288.   char num[15];
  289.   ultoa(n, num, 10);
  290.  
  291.   SetStr(num);
  292. }
  293.  
  294. // double to string
  295. void StrPP::dtos(const double n, const char* format)
  296. {
  297.   char num[40];
  298.  
  299.   if(format[0] != 0 && fpFormat != format)
  300.     fpFormat = format;            // use the format if given
  301.  
  302.   sprintf(num, fpFormat, n);
  303.  
  304.   SetStr(num);
  305. }
  306.  
  307. // Gets the buffer size using strMinLength & strIncLength
  308. int StrPP::GetSize(int n)
  309. {
  310.   bufferLen = strMinLength;        // start with strMinLength
  311.  
  312.   if(n > bufferLen)
  313.   {
  314.     while(n > bufferLen)
  315.       bufferLen += strIncLength;    // incrementally add strIncLength
  316.   }
  317.   bufferLen++;                // add one for NULL termination
  318.  
  319.   return bufferLen;
  320. }
  321.  
  322. int StrPP::SetSize(int len)
  323. {
  324.   if(len < strLen)
  325.     return 0;
  326.  
  327.   bufferLen = len + 1;
  328.   char *tmp = new char[bufferLen];
  329.  
  330.   memcpy(tmp, strPtr, strLen);        // copy the original string
  331.   tmp[strLen] = 0;            // add NULL termination
  332.  
  333.   if(strPtr)                // now make strPtr = tmp
  334.     delete strPtr;
  335.   strPtr = tmp;
  336.  
  337.   return bufferLen-1;
  338. }
  339.  
  340. // Minimize the buffer size to the exact size of the string
  341. void StrPP::Minimize(void)
  342. {
  343.   if(strLen < bufferLen-1)
  344.     SetSize(strLen);
  345. }
  346.  
  347. void StrPP::SetCaseSensitivity(int cs)
  348. {
  349.   if(cs == 0)
  350.     strCompare = stricmp;        // do case-insensitive compare
  351.   else
  352.     strCompare = strcmp;        // do case-sensitive compare
  353. }
  354.  
  355. void StrPP::SetFloatFormat(const char* format)
  356. {
  357.   if(format[0] != 0)
  358.     fpFormat = format;
  359. }
  360.  
  361. /* -------------------------------------------------------------------- */
  362.  
  363. StrPP& StrPP::Right(int len)
  364. {
  365.   SetStr(strPtr, strLen-len, len);
  366.   return *this;
  367. }
  368.  
  369. StrPP& StrPP::Left(int len)
  370. {
  371.   SetStr(strPtr, 0, len);
  372.   return *this;
  373. }
  374.  
  375. StrPP& StrPP::Mid(int pos, int len)
  376. {
  377.   SetStr(strPtr, pos, len);
  378.   return *this;
  379. }
  380.  
  381. StrPP& StrPP::Justify(char type, int len, char mode)
  382. {
  383.   if(mode&TRIM)
  384.     Trim();                // delete outter whitespace
  385.  
  386.   if(strLen >= len && !(mode&CLIP))    // check for out-of-bounds
  387.     return *this;
  388.  
  389.   if(strLen > len && (mode&CLIP))    // check for clipping
  390.   {
  391.     if(type == LEFT)
  392.       Left(len);
  393.     else if(type == CENTER)
  394.       Mid((strLen-len)/2, len);
  395.     else if(type == RIGHT)
  396.       Right(len);
  397.  
  398.     return *this;            // return clipped string
  399.   }
  400.  
  401.   if(type == LEFT)
  402.     *this = *this + StrPP(' ', len-strLen);
  403.   else if(type == CENTER)
  404.     *this = StrPP(' ', (len-strLen)/2) + *this +
  405.             StrPP(' ', len - (len+strLen)/2);
  406.   else if(type == RIGHT)
  407.     *this = StrPP(' ', len-strLen) + *this;
  408.  
  409.   strLen = strlen(strPtr);
  410.   return *this;                // return normal string
  411. }
  412.  
  413. // Convert the string contents to uppercase
  414. StrPP& StrPP::toUpper(void)
  415. {
  416.   for(int i=0; i<strlen(strPtr); i++)
  417.     strPtr[i] = (char)strToUpper(strPtr[i]);
  418.   return *this;
  419. }
  420.  
  421. // Convert the string contents to lowercase
  422. StrPP& StrPP::toLower(void)
  423. {
  424.   for(int i=0; i<strlen(strPtr); i++)
  425.     strPtr[i] = (char)strToLower(strPtr[i]);
  426.   return *this;
  427. }
  428.  
  429. // Return the integer numerical value of the string
  430. int& StrPP::Value(int& n) const
  431. {
  432.   n = atoi(strPtr);
  433.   return n;
  434. }
  435.  
  436. // Return the unsigned integer numerical value of the string
  437. unsigned& StrPP::Value(unsigned& n) const
  438. {
  439.   n = atoi(strPtr);
  440.   return n;
  441. }
  442.  
  443. // Return the long integer numerical value of the string
  444. long& StrPP::Value(long& n) const
  445. {
  446.   n = atol(strPtr);
  447.   return n;
  448. }
  449.  
  450. // Return the unsigned long integer numerical value of the string
  451. unsigned long& StrPP::Value(unsigned long& n) const
  452. {
  453.   n = atol(strPtr);
  454.   return n;
  455. }
  456.  
  457. // Return the float numerical value of the string
  458. float& StrPP::Value(float& n) const
  459. {
  460.   n = (float)atof(strPtr);
  461.   return n;
  462. }
  463.  
  464. // Return the double numerical value of the string
  465. double& StrPP::Value(double& n) const
  466. {
  467.   n = atof(strPtr);
  468.   return n;
  469. }
  470.  
  471. // Insert substring 's' at position 'pos'
  472. StrPP& StrPP::Insert(int pos, const StrPP& s)
  473. {
  474.   if(pos > strLen)            // check for out-of-bounds
  475.     return *this;
  476.  
  477.   if(bufferLen > strLen + s.strLen)    // if the buffer is big enough...
  478.   {
  479.     memmove(strPtr+pos+s.strLen, strPtr+pos, strLen-pos);
  480.     memcpy(strPtr+pos, s.strPtr, s.strLen);
  481.   }
  482.   else                    // need to reallocate the buffer
  483.   {
  484.     GetSize(strLen + s.strLen);
  485.     char* tmp = new char[bufferLen];
  486.  
  487.     memcpy(tmp, strPtr, pos);
  488.     memcpy(tmp+pos, s.strPtr, s.strLen);
  489.     memcpy(tmp+pos+s.strLen, strPtr+pos, strLen-pos);
  490.  
  491.     delete strPtr;
  492.     strPtr = tmp;
  493.   }
  494.   strLen += s.strLen;            // increase strLen
  495.   strPtr[strLen] = 0;            // add NULL termination
  496.  
  497.   return *this;
  498. }
  499.  
  500. // Delete 'len' characters beginning at 'pos'
  501. StrPP& StrPP::Delete(int pos, int len)
  502. {
  503.   if(pos >= strLen)            // check for out-of-bounds
  504.     return *this;
  505.   if(len > strLen - pos)
  506.     len = strLen - pos;
  507.   if(len == 0)
  508.     len = strLen - pos;
  509.  
  510.   strLen -= len;
  511.   memmove(strPtr+pos, strPtr+pos+len, strLen-pos);
  512.   strPtr[strLen] = 0;            // add a new NULL terminator
  513.  
  514.   return *this;
  515. }
  516.  
  517. // Replace 'len' characters beginning at 'pos' with substring 'to'
  518. StrPP& StrPP::Replace(int pos, int len, const StrPP& to)
  519. {
  520.   Delete(pos, len);
  521.   Insert(pos, to);
  522.  
  523.   return *this;
  524. }
  525.  
  526. // Copy the string contents to 'p'
  527. char* StrPP::Copy(char*& p) const
  528. {
  529.   p = new char[strLen + 1];        // allocate memory for p
  530.   memcpy(p, strPtr, strLen);
  531.  
  532.   return p;
  533. }
  534.  
  535. // Trim leading and/or trailing characters from the string. 'c' specifies
  536. // the character to be trimmed and defaults to WHITESPACE (spaces & tabs).
  537. StrPP& StrPP::Trim(int mode, char c)
  538. {
  539.   int begin = 0;
  540.   int end = strLen-1;
  541.  
  542.   if(c == WHITESPACE)            // if we're deleting whitespaces...
  543.   {
  544.     if(mode == LEFT || mode == CENTER)    // delete leading whitespace
  545.     {
  546.       while(isspace(strPtr[begin]) && begin <= end)
  547.         begin++;
  548.     }
  549.  
  550.     if(mode == RIGHT || mode == CENTER)    // delete trailing whitespace
  551.     {
  552.       while(isspace(strPtr[end]) && end >= begin)
  553.         end--;
  554.     }
  555.   }
  556.   else                    // else a character was specified
  557.   {
  558.     if(mode == LEFT || mode == CENTER)    // delete leading characters
  559.     {
  560.       while(strPtr[begin] == c && begin <= end)
  561.         begin++;
  562.     }
  563.  
  564.     if(mode == RIGHT || mode == CENTER)    // delete trailing characters
  565.     {
  566.       while(strPtr[end] == c && end >= begin)
  567.         end--;
  568.     }
  569.   }
  570.  
  571.   SetStr(strPtr, begin, end-begin+1);
  572.   return *this;
  573. }
  574.  
  575. /* ----- Find methods ------------------------------------------------- */
  576.  
  577. // Find the first occurrence of substring 's' in the string
  578. int StrPP::FindFirst(const StrPP& s) const
  579. {
  580.   findPos = index(strPtr, s.strPtr);    // do the search
  581.  
  582.   if(findPos >= 0)            // if 's' was found...
  583.   {
  584.     findIn  = (StrPP*)this;        // ...set the global findIn pointer
  585.     findStr = s;            //   and the global findStr string
  586.   }
  587.   else                    // 's' was not found...
  588.   {
  589.     findIn  = 0;            // ...so reset the global vars
  590.     findStr = 0;
  591.   }
  592.  
  593.   return findPos;            // return the position (-1 if not found)
  594. }
  595.  
  596. // Find the next occurrence of substring 'findStr' in the string
  597. int StrPP::FindNext(void) const
  598. {
  599.   if(findIn != this)            // wrong string, must run FindFirst
  600.     return -1;
  601.   if(findPos >= strLen)            // out-of-bounds
  602.     findPos = -1;
  603.   if(findPos == -1)            // no more occurrences
  604.   {
  605.     findIn  = 0;
  606.     findStr = 0;
  607.     return findPos;
  608.   }
  609.  
  610.   int i = index(strPtr+findPos+1, findStr.strPtr);
  611.  
  612.   if(i == -1)                // findStr not found
  613.   {
  614.     findIn  = 0;
  615.     findStr = 0;
  616.     findPos = -1;
  617.   }
  618.   else
  619.     findPos += i+1;
  620.  
  621.   return findPos;
  622. }
  623.  
  624. // Find the previous occurrence of substring 'findStr' in the string
  625. int StrPP::FindPrev(void) const
  626. {
  627.   if(findIn != this)            // wrong string
  628.     return -1;
  629.   if(findPos < 0)            // out-of-bounds
  630.     findPos = -1;
  631.   if(findPos == -1)            // no more occurrences
  632.   {
  633.     findIn  = 0;
  634.     findStr = 0;
  635.     return findPos;
  636.   }
  637.  
  638.   for(int i = findPos-findStr.strLen; i >= 0; i--)
  639.   {
  640.     if(memcmp(strPtr+i, findStr.strPtr, findStr.strLen) == 0)
  641.     {
  642.       findPos = i;
  643.       return findPos;
  644.     }
  645.   }
  646.   findIn  = 0;                // findStr not found
  647.   findStr = 0;
  648.   findPos = -1;
  649.   return findPos;
  650. }
  651.  
  652. // Find the last occurrence of substring 's' in the string
  653. int StrPP::FindLast(const StrPP& s) const
  654. {
  655.   for(int i = strLen-s.strLen; i > 0; i--)
  656.   {
  657.     if(memcmp(strPtr+i, s.strPtr, s.strLen) == 0)
  658.     {
  659.       findIn  = (StrPP*)this;
  660.       findStr = s;
  661.       findPos = i;
  662.       return findPos;
  663.     }
  664.   }
  665.   findIn  = 0;                // findStr not found
  666.   findStr = 0;
  667.   findPos = -1;
  668.   return findPos;
  669. }
  670.  
  671. /* ----- Operators ---------------------------------------------------- */
  672.  
  673. StrPP StrPP::operator()(int pos, int len) const
  674. {
  675.   StrPP tmp(strPtr, pos, len);
  676.   return tmp;
  677. }
  678.  
  679. StrPP& StrPP::operator=(const char c)
  680. {
  681.   SetStr(c);
  682.   return *this;
  683. }
  684.  
  685. StrPP& StrPP::operator=(const char* p)
  686. {
  687.   SetStr(p);
  688.   return *this;
  689. }
  690.  
  691. StrPP& StrPP::operator=(const StrPP& s)
  692. {
  693.   SetStr(s);
  694.   return *this;
  695. }
  696.  
  697. StrPP& StrPP::operator=(const long n)
  698. {
  699.   ltos(n);
  700.   return *this;
  701. }
  702.  
  703. StrPP& StrPP::operator=(const unsigned long n)
  704. {
  705.   ultos(n);
  706.   return *this;
  707. }
  708.  
  709. StrPP& StrPP::operator=(const double n)
  710. {
  711.   dtos(n, "");
  712.   return *this;
  713. }
  714.  
  715. StrPP& StrPP::operator+=(const char c)
  716. {
  717.   AddStr(c);
  718.   return *this;
  719. }
  720.  
  721. StrPP& StrPP::operator+=(const char* p)
  722. {
  723.   AddStr(p);
  724.   return *this;
  725. }
  726.  
  727. StrPP& StrPP::operator+=(const StrPP& s)
  728. {
  729.   AddStr(s);
  730.   return *this;
  731. }
  732.  
  733. StrPP operator+(const StrPP& s, const char* p)
  734. {
  735.   StrPP tmp(s);
  736.   tmp.AddStr(p);
  737.   return tmp;
  738. }
  739.  
  740. StrPP operator+(const char* p, const StrPP& s)
  741. {
  742.   StrPP tmp(p);
  743.   tmp.AddStr(s);
  744.   return tmp;
  745. }
  746.  
  747. StrPP operator+(const StrPP& s1, const StrPP& s2)
  748. {
  749.   StrPP tmp(s1);
  750.   tmp.AddStr(s2);
  751.   return tmp;
  752. }
  753.  
  754. StrPP operator*(const StrPP& s1, const int n)
  755. {
  756.   StrPP tmp(s1);
  757.  
  758.   for(int i=1; i<n; i++)
  759.     tmp += s1;
  760.   return tmp;
  761. }
  762.  
  763. StrPP operator*(const int n, const StrPP& s1)
  764. {
  765.   StrPP tmp(s1);
  766.  
  767.   for(int i=1; i<n; i++)
  768.     tmp += s1;
  769.   return tmp;
  770. }
  771.  
  772. StrPP& StrPP::operator*=(const int n)
  773. {
  774.   int nlen = n*strLen;
  775.  
  776.   if(bufferLen > nlen)
  777.   {
  778.     for(int i=0; i<n; i++)
  779.       memcpy(strPtr+i*strLen, strPtr, strLen);
  780.     strPtr[nlen] = 0;
  781.   }
  782.   else
  783.   {
  784.     char *tmp = new char[nlen + 1];
  785.  
  786.     for(int i=0; i<n; i++)
  787.       memcpy(tmp+i*strLen, strPtr, strLen);
  788.      tmp[nlen] = 0;
  789.  
  790.     SetStr(tmp);
  791.   }
  792.   return *this;
  793. }
  794.  
  795. char& StrPP::operator[](const int n) const
  796. {
  797.   if(n > strLen)
  798.     return *(strPtr + strLen);
  799.   return *(strPtr + n);
  800. }
  801.  
  802. StrPP& StrPP::operator<<(const char c)
  803. {
  804.   AddStr(c);
  805.   return *this;
  806. }
  807.  
  808. StrPP& StrPP::operator<<(const char* p)
  809. {
  810.   AddStr(p);
  811.   return *this;
  812. }
  813.  
  814. StrPP& StrPP::operator<<(const StrPP& s)
  815. {
  816.   AddStr(s);
  817.   return *this;
  818. }
  819.  
  820. StrPP& StrPP::operator<<(const long n)
  821. {
  822.   char num[15];
  823.   ltoa(n, num, 10);
  824.   AddStr(num);
  825.  
  826.   return *this;
  827. };
  828.  
  829. StrPP& StrPP::operator<<(const unsigned long n)
  830. {
  831.   char num[15];
  832.   ultoa(n, num, 10);
  833.   AddStr(num);
  834.  
  835.   return *this;
  836. };
  837.  
  838. StrPP& StrPP::operator<<(const double n)
  839. {
  840.   StrPP tmp(n);
  841.   AddStr(tmp);
  842.   return *this;
  843. };
  844.  
  845. /* -------------------------------------------------------------------- */
  846. /* AWK-style functions                                                  */
  847. /* -------------------------------------------------------------------- */
  848.  
  849. int index(const char* s, const char* t)
  850. {
  851.   int pos;
  852.   const char *tmp;
  853.  
  854.   if((tmp = strstr(s, t)) != NULL)
  855.     pos = (int)(tmp-s);
  856.   else
  857.     pos = -1;
  858.  
  859.   return pos;
  860. }
  861.  
  862. StrPP substr(const StrPP& s, int pos, int len)
  863. {
  864.   StrPP tmp(s, pos, len);
  865.   return tmp;
  866. }
  867.  
  868. int split(const StrPP& s, StrPP*& array, const StrPP& fs)
  869. {
  870.   int i=0, j=0, start=0;
  871.   StrPP *tmp;
  872.  
  873.   while(i < s.Len())            // find the number of substrings
  874.   {
  875.     if(memcmp(s(i), fs(), fs.Len()) == 0)
  876.       j++;
  877.     i++;
  878.   }
  879.   if(j == 0)
  880.     return 0;
  881.  
  882.   tmp = new StrPP[j+1];            // allocate the array of strings
  883.   i = 0;
  884.   j = 0;
  885.  
  886.   while(i < s.Len())            // fill in the array
  887.   {
  888.     if(memcmp(s(i), fs(), fs.Len()) == 0)
  889.     {
  890.       tmp[j++] = mid(s, start, i-start);
  891.       i += fs.Len();
  892.       start = i;
  893.     }
  894.     else
  895.       i++;
  896.   }
  897.   tmp[j++] = mid(s, start, i-start);
  898.  
  899.   array = tmp;
  900.   return j;
  901. }
  902.  
  903. int gsub(const StrPP& from, const StrPP& to, StrPP& s, int count)
  904. {
  905.   int i=0, j=0;
  906.  
  907.   while(i <= s.Len() - from.Len())
  908.   {
  909.     if(memcmp(s(i), from(), from.Len()) == 0)
  910.     {
  911.       s = left(s, i) + to + right(s, s.Len()-i-from.Len());
  912.       i += to.Len();
  913.       if(++j == count)
  914.         break;
  915.     }
  916.     else
  917.       i++;
  918.   }
  919.   return j;
  920. }
  921.  
  922. /* -------------------------------------------------------------------- */
  923. /* C-style functions (return copies of strings)                         */
  924. /* -------------------------------------------------------------------- */
  925.  
  926. StrPP toupper(const StrPP& s)
  927. {
  928.   StrPP tmp(s);
  929.   tmp.toUpper();
  930.   return tmp;
  931. }
  932.  
  933. StrPP tolower(const StrPP& s)
  934. {
  935.   StrPP tmp(s);
  936.   tmp.toLower();
  937.   return tmp;
  938. }
  939.  
  940. StrPP left(const char* p, int len)
  941. {
  942.   StrPP tmp(p, 0, len);
  943.   return tmp;
  944. }
  945.  
  946. StrPP right(const char* p, int len)
  947. {
  948.   StrPP tmp(p, strlen(p)-len, len);
  949.   return tmp;
  950. }
  951.  
  952. StrPP mid(const char* p, int pos, int len)
  953. {
  954.   StrPP tmp(p, pos, len);
  955.   return tmp;
  956. }
  957.  
  958. StrPP justify(const char* p, char type, int len, char mode)
  959. {
  960.   StrPP tmp(p);
  961.   tmp.Justify(type, len, mode);
  962.   return tmp;
  963. }
  964.  
  965. StrPP trim(const char* p, int mode)
  966. {
  967.   StrPP tmp(p);
  968.   tmp.Trim(mode);
  969.   return tmp;
  970. }
  971.  
  972. /* ----- Stream I/O --------------------------------------------------- */
  973.  
  974. ostream& operator<<(ostream& strm, const StrPP& s)
  975. {
  976.   return strm << s();
  977. }
  978.  
  979. istream& operator>>(istream& strm, StrPP& s)
  980. {
  981.   char p[256];
  982.  
  983.   strm >> p;
  984.   s = p;
  985.  
  986.   return strm;
  987. }
  988.